/*
 * 文件名： WechatWcpayCiticManager.java
 * 
 * 工程名称: bis-manager
 *
 * Gopay
 *
 * 创建日期： 2016年10月11日
 *
 * Copyright(C) 2016, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.manager.bank.wcpay;

import java.util.Date;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.wechat.wcpay.citic.req.WcPayQueryReqMsg;
import com.gopay.common.domain.bank.wechat.wcpay.citic.req.WcPayReqMsg;
import com.gopay.common.domain.bank.wechat.wcpay.citic.req.WcRefundQueryReqMsg;
import com.gopay.common.domain.bank.wechat.wcpay.citic.req.WcRefundReqMsg;
import com.gopay.common.domain.bank.wechat.wcpay.citic.res.WcPayQueryResMsg;
import com.gopay.common.domain.bank.wechat.wcpay.citic.res.WcPayResMsg;
import com.gopay.common.domain.bank.wechat.wcpay.citic.res.WcRefundQueryResMsg;
import com.gopay.common.domain.bank.wechat.wcpay.citic.res.WcRefundResMsg;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.TransUtil;
import com.gopay.remote.bank.businesses.WcPayService;
import com.ibm.icu.util.Calendar;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * 微信公众号支付中信银行通道报文拼装处理
 *
 * @author 宣广海
 *
 * @version
 *
 * @since 2016年10月11日
 */
public class WechatWcpayCiticManager {
	/**
	 * 日志对象
	 */
	private static Logger logger = LoggerFactory.getLogger(WechatWcpayCiticManager.class);

	/**
	 * 注入对象
	 */
	@Resource(name = "wechatWcPayConfig")
	private Map<String, String> wechatWcPayConfig;

	@Resource(name = "wechatWcPayCiticServiceClient")
	private WcPayService wechatWcPayCiticServiceClient;
	private static long seed = 0;

	/**
	 * 
	 * 功能描述：组装签名报文
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2016年10月11日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object sign(BaseMessage msg) throws GopayException {
		WcPayResMsg resMessage = new WcPayResMsg();
		try {
			msg.setBankOrderId(modifyOrderId(msg.getOrderId()));
			WcPayReqMsg message = (WcPayReqMsg) msg;
			message.setService(wechatWcPayConfig.get("WECHATWC.PAY.SEVICE"));
			message.setVersion(wechatWcPayConfig.get("WECHATWC.PAY.VERSION"));
			message.setCharset(wechatWcPayConfig.get("WECHATWC.PAY.CHARSET"));
			message.setSign_type(wechatWcPayConfig.get("WECHATWC.PAY.SIGN.TYPE"));
			message.setIs_raw(wechatWcPayConfig.get("WECHATWC.PAY.IS.RAW"));
			message.setMch_id(message.getMerID());
			message.setCustomerID("");
			message.setOut_trade_no(message.getBankOrderId());
			message.setDevice_info(message.getDeviceInfo());
			message.setBody(message.getGoodsBody());
			/**
			 * 测试的时候不需要上送这个参数
			 */
			if("7551000001".equals(message.getMerID())){
				//message.setSub_openid(message.getSubOpenId());
				message.setPrivateKeyPath("9d101c97133837e13dde2d32a5054abb");
			}else{
				message.setSub_openid(message.getSubOpenId());
			}
			
			message.setLimit_credit_pay(message.getLimitCreditPay());
			message.setAttach("");
			/**
			 * 金额精确到分
			 */
			message.setTotal_fee(TransUtil.amountConvert2Fen(message.getAmount().toString()));
			message.setMch_create_ip(message.getMchCreateIp());
			message.setNotify_url(message.getPayRuturnUrl());
			message.setCallback_url("");
			message.setTime_start(DateUtils.format(new Date()));
			/**
			 * 订单失效时间目前是6分钟后失效
			 */
			message.setTime_expire(
					DateUtils.format(DateUtils.add(DateUtils.strToDate(message.getTime_start()), Calendar.MINUTE, 6)));
			message.setGoods_tag(message.getGoodsTag());
			/**
			 * 随机字符串
			 */
			message.setNonce_str(creatSerialNumber(20));
			message.setPlainMessage(buildPlain(message));
			logger.info("WECHAT wcPay manager sign message :" + ToStringBuilder.reflectionToString(resMessage));
			resMessage = (WcPayResMsg) wechatWcPayCiticServiceClient.payment(message);
			logger.info("WECHAT wcPay manager sign return message :" + ToStringBuilder.reflectionToString(resMessage));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025, e);
		}
		return resMessage;
	}

	/**
	 * 
	 * 功能描述：异步通知验签
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2016年10月12日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object verify(BaseMessage msg) throws GopayException {
		boolean falg = false;
		try {
			logger.info("WECHAT wcPay manager verify message :" + ToStringBuilder.reflectionToString(msg));
			falg = (boolean) wechatWcPayCiticServiceClient.verify(msg);
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026, e);
		}
		return falg;
	}

	/**
	 * 
	 * 功能描述：构建查询请求报文
	 *
	 * @param obj
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2016年10月12日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object orderQuery(BaseMessage msg) throws GopayException {
		WcPayQueryResMsg resMsg = new WcPayQueryResMsg();
		try {
			WcPayQueryReqMsg message = (WcPayQueryReqMsg) msg;
			message.setService(wechatWcPayConfig.get("WECHATWC.ORDERQUERY.SEVICE"));
			message.setVersion(wechatWcPayConfig.get("WECHATWC.PAY.VERSION"));
			message.setCharset(wechatWcPayConfig.get("WECHATWC.PAY.CHARSET"));
			message.setSign_type(wechatWcPayConfig.get("WECHATWC.PAY.SIGN.TYPE"));
			message.setMch_id(message.getMerID());
			message.setOut_trade_no(message.getBankOrderId());
			message.setNonce_str(creatSerialNumber(20));// 随机字符串
			message.setPlainMessage(buildPlain(message));
			logger.info("WECHAT wcPay manager query  message :" + ToStringBuilder.reflectionToString(message));
			resMsg = (WcPayQueryResMsg) wechatWcPayCiticServiceClient.queryOrder(message);
			logger.info("WECHAT wcPay manager query return message :" + ToStringBuilder.reflectionToString(resMsg));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7027, e);
		}
		return resMsg;
	}

	/**
	 * 
	 * 功能描述：构建退款请求报文
	 *
	 * @param obj
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2016年10月18日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object refund(BaseMessage obj) throws GopayException {
		WcRefundResMsg resMsg = new WcRefundResMsg();
		try {
			WcRefundReqMsg message = (WcRefundReqMsg) obj;
			message.setService(wechatWcPayConfig.get("WECHATWC.REFUND.SEVICE"));
			message.setVersion(wechatWcPayConfig.get("WECHATWC.PAY.VERSION"));
			message.setCharset(wechatWcPayConfig.get("WECHATWC.PAY.CHARSET"));
			message.setSign_type(wechatWcPayConfig.get("WECHATWC.PAY.SIGN.TYPE"));
			message.setMch_id(message.getMerID());
			 /**
             * 原交易上送银行订单号
             */
            message.setOut_trade_no(message.getTkOriBankOrderId());
            /**
             * 退款订单号
             */
            message.setOut_refund_no(message.getBankOrderId());
			message.setTotal_fee(TransUtil.amountConvert2Fen(message.getTkOriAmount().toString()));
			message.setRefund_fee(TransUtil.amountConvert2Fen(message.getAmount().toString()));
			message.setOp_user_id(message.getMerID());

			message.setNonce_str(creatSerialNumber(20));
			message.setPlainMessage(buildPlain(message));

			message.setRefundUrl(wechatWcPayConfig.get("WECHATWC.REFUND.URL"));
			logger.info("WECHAT WCPAY manager refund send message:" + ToStringBuilder.reflectionToString(message));
			resMsg = (WcRefundResMsg) wechatWcPayCiticServiceClient.refund(message);
			logger.info("WECHAT WCPAY manager refund return message:" + ToStringBuilder.reflectionToString(resMsg));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1160, e);
		}
		return resMsg;
	}

	/**
	 * 
	 * 功能描述：退款查询构建报文
	 *
	 * @param obj
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2016年10月18日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object refundQuery(BaseMessage obj) throws GopayException {
		WcRefundQueryResMsg resMsg = new WcRefundQueryResMsg();
		try {
			WcRefundQueryReqMsg message = (WcRefundQueryReqMsg) obj;
			message.setService(wechatWcPayConfig.get("WECHATWC.REFUNDQUERY.SEVICE"));
			message.setVersion(wechatWcPayConfig.get("WECHATWC.PAY.VERSION"));
			message.setCharset(wechatWcPayConfig.get("WECHATWC.PAY.CHARSET"));
			message.setSign_type(wechatWcPayConfig.get("WECHATWC.PAY.SIGN.TYPE"));
			message.setMch_id(message.getMerID());
			message.setOut_trade_no(message.getTkOriBankOrderId());
			message.setTransaction_id("");
			/**
			 * 商户退款单号
			 */
			message.setOut_refund_no(message.getBankOrderId());
			message.setRefund_id("");
			message.setNonce_str(creatSerialNumber(20));
			message.setPlainMessage(buildPlain(message));
			/**
			 * 退款订单查询
			 */
			message.setRefundQueryUrl(wechatWcPayConfig.get("WECHATWC.REFUNDQUERY.URL"));
			logger.info("WECHAT WCPAY manager refundQuery send message:" + ToStringBuilder.reflectionToString(message));
			resMsg = (WcRefundQueryResMsg) wechatWcPayCiticServiceClient.refundQuery(message);
			logger.info("WECHAT WCPAY manager refundQuery return message:" + ToStringBuilder.reflectionToString(resMsg));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E5062, e);
		}
		return resMsg;
	}

	/**
	 * 
	 * 功能描述：
	 *
	 * @param orderId
	 * @return
	 * 
	 * @author 宣广海
	 *
	 * @since 2016年10月11日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	private static String modifyOrderId(String orderId) {

		return "WF" + orderId.substring(2);

	}

	/**
	 * 
	 * 功能描述：
	 *
	 * @param length
	 * @return
	 * 
	 * @author 宣广海
	 *
	 * @since 2016年10月12日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static String creatSerialNumber(int length) {
		byte[] randomSerial = new byte[length];
		String charactors = "123456789abcdefghigklmnopkrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
		int charSetLength = charactors.length();
		seed = seed ^ System.currentTimeMillis();
		java.util.Random randomNumber = new java.util.Random(seed);

		for (int i = 0; i < length; i++) {
			randomNumber.setSeed(seed);
			int j = (int) (randomNumber.nextFloat() * charSetLength);
			randomSerial[i] = (byte) charactors.charAt(j);
			seed = seed ^ randomNumber.nextInt();
		}
		return (new String(randomSerial));
	}

	/**
	 * 
	 * 功能描述：拼装需要签名报文
	 *
	 * @param obj
	 * @return
	 * @throws Exception
	 * 
	 * @author 宣广海
	 *
	 * @since 2016年10月12日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public String buildPlain(Object obj) throws Exception {
		// 去掉多一个下划线的问题
		XStream xstream = new XStream(new DomDriver("UTF-8", new NoNameCoder()));
		xstream.processAnnotations(obj.getClass());
		return xstream.toXML(obj);
	}
}
